﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BibMan.model.database;
using BibMan.model;
using BibMan.model.database.bibtex;
using System.Text.RegularExpressions;

namespace BibMan.controller {
    public class Searcher {

        public String Query { get; set; }

        private HashSet<String> searchTags;
        public HashSet<String> SearchTags {
            get {
                return searchTags;
            }
        }

        private List<String> searchSet;
        public List<String> SearchSet {
            get {
                return searchSet;
            }
            set {
                searchSet = value ?? new List<String>();
            }
        }

        public Searcher(String query = null) {
            this.Query = query ?? String.Empty;
            this.searchTags = new HashSet<String>();
            SearchSet = new List<String>();
        }

        public IEnumerable<String> Search() {
            if (Query.Equals(String.Empty) && SearchSet.Count == 0) return Model.Instance.Database.ConvertAll<String>(r => r.Id);
            if (SearchTags.Count > 0) {
                return SearchSet.Where(id => IsRestrictedMatch(id, Query));
            }
            return SearchSet.Where(id => IsMatch(id, Query));
        }

        private bool IsMatch(String id, String query) {
            if (Regex.IsMatch(id, query, RegexOptions.IgnoreCase)) return true;
            Reference item = Model.Instance.Database[id];
            if (item.Pins.Any(name => Regex.IsMatch(name, query, RegexOptions.IgnoreCase)))
                return true;
            if (item.BibItem.Any<KeyValuePair<String, String>>(
                    tag => Regex.IsMatch(tag.Value, query, RegexOptions.IgnoreCase))) 
                return true;
            return false;
        }

        private bool IsRestrictedMatch(String id, String query) {
            if (Regex.IsMatch(id, query, RegexOptions.IgnoreCase)) return true;
            Reference item = Model.Instance.Database[id];
            foreach (String tag in searchTags) {
                if (item.Pins.Any(name => Regex.IsMatch(name, query, RegexOptions.IgnoreCase)))
                    return true;
                if (Regex.IsMatch(item.BibItem[tag], query, RegexOptions.IgnoreCase))
                    return true;
            }            
            return false;
        }

    }
}
